//
//  UPKeychainManager.m
//  Uang Pasti
//
//  Created by 李永彬 on 2025/8/16.
//

#import "UPKeychainManager.h"
#import <Security/Security.h>

@implementation UPKeychainManager

+ (instancetype)sharedManager {
    static UPKeychainManager *instance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        instance = [[UPKeychainManager alloc] init];
    });
    return instance;
}

#pragma mark - 基础Keychain操作

- (NSMutableDictionary *)getKeychainQuery:(NSString *)key {
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass,
            key, (__bridge id)kSecAttrService,
            key, (__bridge id)kSecAttrAccount,
            (__bridge id)kSecAttrAccessibleAfterFirstUnlock, (__bridge id)kSecAttrAccessible,
            nil];
}

- (BOOL)saveData:(id)data forKey:(NSString *)key {
    if (!key || !data) {
        return NO;
    }
    
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
    SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data]
                      forKey:(__bridge id)kSecValueData];
    
    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
    return status == errSecSuccess;
}

- (nullable id)readDataForKey:(NSString *)key {
    if (!key) {
        return nil;
    }
    
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
    [keychainQuery setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
    [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    
    CFTypeRef result = NULL;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, &result);
    
    if (status != errSecSuccess) {
        return nil;
    }
    
    NSData *data = (__bridge_transfer NSData *)result;
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

- (BOOL)deleteDataForKey:(NSString *)key {
    if (!key) {
        return NO;
    }
    
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:key];
    OSStatus status = SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
    return status == errSecSuccess || status == errSecItemNotFound;
}

#pragma mark - 字符串便捷方法

- (BOOL)saveString:(NSString *)string forKey:(NSString *)key {
    return [self saveData:string forKey:key];
}

- (nullable NSString *)readStringForKey:(NSString *)key {
    id data = [self readDataForKey:key];
    if ([data isKindOfClass:[NSString class]]) {
        return (NSString *)data;
    }
    return nil;
}

@end
